home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 3.iso / dist / fw_elisp-intro.idb / usr / freeware / info / emacs-lisp-intro.info-13.z / emacs-lisp-intro.info-13
Encoding:
GNU Info File  |  1998-10-28  |  46.6 KB  |  1,155 lines

  1. This is Info file emacs-lisp-intro.info, produced by Makeinfo version
  2. 1.67 from the input file emacs-lisp-intro.texi.
  3.  
  4.    This is an introduction to `Programming in Emacs Lisp', for people
  5. who are not programmers.
  6.  
  7.    Edition 1.05, 21 October 1997
  8.  
  9.    Copyright (C) 1990, '91, '92, '93, '94, '95, '97 Free Software
  10. Foundation, Inc.
  11.  
  12.    Permission is granted to make and distribute verbatim copies of this
  13. manual provided the copyright notice and this permission notice are
  14. preserved on all copies.
  15.  
  16.    Permission is granted to copy and distribute modified versions of
  17. this manual under the conditions for verbatim copying, provided also
  18. that the sections entitled "Copying" and "GNU General Public License"
  19. are included exactly as in the original, and provided that the entire
  20. resulting derived work is distributed under the terms of a permission
  21. notice identical to this one.
  22.  
  23.    Permission is granted to copy and distribute translations of this
  24. manual into another language, under the above conditions for modified
  25. versions, except that this permission notice may be stated in a
  26. translation approved by the Free Software Foundation.
  27.  
  28. 
  29. File: emacs-lisp-intro.info,  Node: X Axis Tic Marks,  Prev: print-X-axis,  Up: print-X-axis
  30.  
  31. X Axis Tic Marks
  32. ----------------
  33.  
  34.    The first function should print the X axis tic marks.  We must
  35. specify the tic marks themselves and their spacing:
  36.  
  37.      (defvar X-axis-label-spacing
  38.        (if (boundp 'graph-blank)
  39.            (* 5 (length graph-blank)) 5)
  40.        "Number of units from one X axis label to next.")
  41.  
  42. (Note that the value of `graph-blank' is set by another `defvar'.  The
  43. `boundp' predicate checks whether it has already been set; `boundp'
  44. returns `nil' if it has not.  If `graph-blank' were unbound and we did
  45. not use this conditional construction, we would receive an error
  46. message saying `Symbol's value as variable is void'.)
  47.  
  48.      (defvar X-axis-tic-symbol "|"
  49.        "String to insert to point to a column in X axis.")
  50.  
  51.    The goal is to make a line that looks like this:
  52.  
  53.             |   |    |    |
  54.  
  55.    The first tic is indented so that it is under the first column,
  56. which is indented to provide space for the Y axis labels.
  57.  
  58.    A tic element consists of the blank spaces that stretch from one tic
  59. to the next plus a tic symbol.  The number of blanks is determined by
  60. the width of the tic symbol and the `X-axis-label-spacing'.
  61.  
  62.    The code looks like this:
  63.  
  64.      ;;; X-axis-tic-element
  65.      ...
  66.      (concat
  67.       (make-string
  68.        ;; Make a string of blanks.
  69.        (-  (* symbol-width X-axis-label-spacing)
  70.            (length X-axis-tic-symbol))
  71.        ? )
  72.       ;; Concatenate blanks with tic symbol.
  73.       X-axis-tic-symbol)
  74.      ...
  75.  
  76.    Next, we determine how many blanks are needed to indent the first tic
  77. mark to the first column of the graph.  This uses the value of
  78. `full-Y-label-width' passed it by the `print-graph' function.
  79.  
  80.    The code to make `X-axis-leading-spaces' looks like this:
  81.  
  82.      ;; X-axis-leading-spaces
  83.      ...
  84.      (make-string full-Y-label-width ? )
  85.      ...
  86.  
  87.    We also need to determine the length of the horizontal axis, which is
  88. the length of the numbers list, and the number of tics in the horizontal
  89. axis:
  90.  
  91.      ;; X-length
  92.      ...
  93.      (length numbers-list)
  94.      
  95.      ;; tic-width
  96.      ...
  97.      (* symbol-width X-axis-label-spacing)
  98.      
  99.      ;; number-of-X-tics
  100.      (if (zerop (% (X-length tic-width)))
  101.          (/ (X-length tic-width))
  102.        (1+ (/ (X-length tic-width))))
  103.  
  104.    All this leads us directly to the function for printing the X axis
  105. tic line:
  106.  
  107.      (defun print-X-axis-tic-line
  108.        (number-of-X-tics X-axis-leading-spaces X-axis-tic-element)
  109.        "Print tics for X axis."
  110.          (insert X-axis-leading-spaces)
  111.          (insert X-axis-tic-symbol)  ; Under first column.
  112.          ;; Insert second tic in the right spot.
  113.          (insert (concat
  114.                   (make-string
  115.                    (-  (* symbol-width X-axis-label-spacing)
  116.                        ;; Insert white space up to second tic symbol.
  117.                        (* 2 (length X-axis-tic-symbol)))
  118.                    ? )
  119.                   X-axis-tic-symbol))
  120.          ;; Insert remaining tics.
  121.          (while (> number-of-X-tics 1)
  122.            (insert X-axis-tic-element)
  123.            (setq number-of-X-tics (1- number-of-X-tics))))
  124.  
  125.    The line of numbers is equally straightforward:
  126.  
  127.    First, we create a numbered element with blank spaces before each
  128. number:
  129.  
  130.      (defun X-axis-element (number)
  131.        "Construct a numbered X axis element."
  132.        (let ((leading-spaces
  133.               (-  (* symbol-width X-axis-label-spacing)
  134.                   (length (int-to-string number)))))
  135.          (concat (make-string leading-spaces ? )
  136.                  (int-to-string number))))
  137.  
  138.    Next, we create the function to print the numbered line, starting
  139. with the number "1" under the first column:
  140.  
  141.      (defun print-X-axis-numbered-line
  142.        (number-of-X-tics X-axis-leading-spaces)
  143.        "Print line of X-axis numbers"
  144.        (let ((number X-axis-label-spacing))
  145.          (insert X-axis-leading-spaces)
  146.          (insert "1")
  147.          (insert (concat
  148.                   (make-string
  149.                    ;; Insert white space up to next number.
  150.                    (-  (* symbol-width X-axis-label-spacing) 2)
  151.                    ? )
  152.                   (int-to-string number)))
  153.          ;; Insert remaining numbers.
  154.          (setq number (+ number X-axis-label-spacing))
  155.          (while (> number-of-X-tics 1)
  156.            (insert (X-axis-element number))
  157.            (setq number (+ number X-axis-label-spacing))
  158.            (setq number-of-X-tics (1- number-of-X-tics)))))
  159.  
  160.    Finally, we need to write the `print-X-axis' that uses
  161. `print-X-axis-tic-line' and `print-X-axis-numbered-line'.
  162.  
  163.    The function must determine the local values of the variables used
  164. by both `print-X-axis-tic-line' and `print-X-axis-numbered-line', and
  165. then it must call them.  Also, it must print the carriage return that
  166. separates the two lines.
  167.  
  168.    The function consists of a varlist that specifies five local
  169. variables, and calls to each of the two line printing functions:
  170.  
  171.      (defun print-X-axis (numbers-list)
  172.        "Print X axis labels to length of NUMBERS-LIST."
  173.        (let* ((leading-spaces
  174.                (make-string full-Y-label-width ? ))
  175.             ;; symbol-width is provided by graph-body-print
  176.             (tic-width (* symbol-width X-axis-label-spacing))
  177.             (X-length (length numbers-list))
  178.             (X-tic
  179.              (concat
  180.               (make-string
  181.                ;; Make a string of blanks.
  182.                (-  (* symbol-width X-axis-label-spacing)
  183.                    (length X-axis-tic-symbol))
  184.                ? )
  185.               ;; Concatenate blanks with tic symbol.
  186.               X-axis-tic-symbol))
  187.             (tic-number
  188.              (if (zerop (% X-length tic-width))
  189.                  (/ X-length tic-width)
  190.                (1+ (/ X-length tic-width)))))
  191.          (print-X-axis-tic-line tic-number leading-spaces X-tic)
  192.          (insert "\n")
  193.          (print-X-axis-numbered-line tic-number leading-spaces)))
  194.  
  195.    You can test `print-X-axis':
  196.  
  197.   1. Install `X-axis-tic-symbol', `X-axis-label-spacing',
  198.      `print-X-axis-tic-line', as well as `X-axis-element',
  199.      `print-X-axis-numbered-line', and `print-X-axis'.
  200.  
  201.   2. Copy the following expression:
  202.  
  203.           (progn
  204.            (let ((full-Y-label-width 5)
  205.                  (symbol-width 1))
  206.              (print-X-axis
  207.               '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))))
  208.  
  209.   3. Switch to the `*scratch*' buffer and place the cursor where you
  210.      want the axis labels to start.
  211.  
  212.   4. Type `M-:' (`eval-expression').
  213.  
  214.   5. Yank the test expression into the minibuffer with `C-y' (`yank)'.
  215.  
  216.   6. Press <RET> to evaluate the expression.
  217.  
  218.    Emacs will print the horizontal axis like this:
  219.  
  220.           |   |    |    |    |
  221.           1   5   10   15   20
  222.  
  223. 
  224. File: emacs-lisp-intro.info,  Node: Print Whole Graph,  Prev: print-X-axis,  Up: Full Graph
  225.  
  226. Printing the Whole Graph
  227. ========================
  228.  
  229.    Now we are nearly ready to print the whole graph.
  230.  
  231.    The function to print the graph with the proper labels follows the
  232. outline we created earlier (*note A Graph with Labelled Axes: Full
  233. Graph.), but with additions.
  234.  
  235.    Here is the outline:
  236.  
  237.      (defun print-graph (numbers-list)
  238.        "DOCUMENTATION..."
  239.        (let ((height  ...
  240.              ...))
  241.          (print-Y-axis height ... )
  242.          (graph-body-print numbers-list)
  243.          (print-X-axis ... )))
  244.  
  245.    The final version is different from what we planned in two ways:
  246. first, it contains additional values calculated once in the varlist;
  247. second, it carries an option to specify the labels' increment per row.
  248. This latter feature turns out to be essential; otherwise a graph may
  249. have more rows than fit on a display or on a sheet of paper.
  250.  
  251.    This new feature requires a change to the `Y-axis-column' function,
  252. to add `vertical-step' to it.  The function looks like this:
  253.  
  254.      ;;; Final version.
  255.      (defun Y-axis-column
  256.        (height width-of-label &optional vertical-step)
  257.        "Construct list of labels for Y axis.
  258.      HEIGHT is maximum height of graph.
  259.      WIDTH-OF-LABEL is maximum width of label.
  260.      VERTICAL-STEP, an option, is a positive integer
  261.      that specifies how much a Y axis label increments
  262.      for each line.  For example, a step of 5 means
  263.      that each line is five units of the graph."
  264.        (let (Y-axis
  265.              (number-per-line (or vertical-step 1)))
  266.          (while (> height 1)
  267.            (if (zerop (% height Y-axis-label-spacing))
  268.                ;; Insert label.
  269.                (setq Y-axis
  270.                      (cons
  271.                       (Y-axis-element
  272.                        (* height number-per-line)
  273.                        width-of-label)
  274.                       Y-axis))
  275.              ;; Else, insert blanks.
  276.              (setq Y-axis
  277.                    (cons
  278.                     (make-string width-of-label ? )
  279.                     Y-axis)))
  280.            (setq height (1- height)))
  281.          ;; Insert base line.
  282.          (setq Y-axis (cons (Y-axis-element
  283.                              (or vertical-step 1)
  284.                              width-of-label)
  285.                             Y-axis))
  286.          (nreverse Y-axis)))
  287.  
  288.    The values for the maximum height of graph and the width of a symbol
  289. are computed by `print-graph' in its `let' expression; so
  290. `graph-body-print' must be changed to accept them.
  291.  
  292.      ;;; Final version.
  293.      (defun graph-body-print (numbers-list height symbol-width)
  294.        "Print a bar graph of the NUMBERS-LIST.
  295.      The numbers-list consists of the Y-axis values.
  296.      HEIGHT is maximum height of graph.
  297.      SYMBOL-WIDTH is number of each column."
  298.        (let (from-position)
  299.          (while numbers-list
  300.            (setq from-position (point))
  301.            (insert-rectangle
  302.             (column-of-graph height (car numbers-list)))
  303.            (goto-char from-position)
  304.            (forward-char symbol-width)
  305.            ;; Draw graph column by column.
  306.            (sit-for 0)
  307.            (setq numbers-list (cdr numbers-list)))
  308.          ;; Place point for X axis labels.
  309.          (forward-line height)
  310.          (insert "\n")))
  311.  
  312.    Finally, the code for the `print-graph' function:
  313.  
  314.      ;;; Final version.
  315.      (defun print-graph
  316.        (numbers-list &optional vertical-step)
  317.        "Print labelled bar graph of the NUMBERS-LIST.
  318.      The numbers-list consists of the Y-axis values.
  319.      
  320.      Optionally, VERTICAL-STEP, a positive integer,
  321.      specifies how much a Y axis label increments for
  322.      each line.  For example, a step of 5 means that
  323.      each row is five units."
  324.        (let* ((symbol-width (length graph-blank))
  325.               ;; `height' is both the largest number
  326.               ;; and the number with the most digits.
  327.               (height (apply 'max numbers-list))
  328.               (height-of-top-line
  329.                (if (zerop (% height Y-axis-label-spacing))
  330.                    height
  331.                  ;; else
  332.                  (* (1+ (/ height Y-axis-label-spacing))
  333.                     Y-axis-label-spacing)))
  334.               (vertical-step (or vertical-step 1))
  335.               (full-Y-label-width
  336.                (length
  337.                 (concat
  338.                  (int-to-string
  339.                   (* height-of-top-line vertical-step))
  340.                  Y-axis-tic))))
  341.      
  342.          (print-Y-axis
  343.           height-of-top-line full-Y-label-width vertical-step)
  344.          (graph-body-print
  345.           numbers-list height-of-top-line symbol-width)
  346.          (print-X-axis numbers-list)))
  347.  
  348. * Menu:
  349.  
  350. * Test print-graph::            Run a short test.
  351. * Graphing words in defuns::    Executing the final code.
  352. * Final Printed Graph::         The graph itself!
  353.  
  354. 
  355. File: emacs-lisp-intro.info,  Node: Test print-graph,  Next: Graphing words in defuns,  Prev: Print Whole Graph,  Up: Print Whole Graph
  356.  
  357. Testing `print-graph'
  358. ---------------------
  359.  
  360.    We can test the `print-graph' function with a short list of numbers
  361.  
  362.   1. Install the final versions of `Y-axis-column', `graph-body-print',
  363.      and `print-graph' (in addition to the rest of the code.)
  364.  
  365.   2. Copy the following expression:
  366.  
  367.           (print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1))
  368.  
  369.   3. Switch to the `*scratch*' buffer and place the cursor where you
  370.      want the axis labels to start.
  371.  
  372.   4. Type `M-:' (`eval-expression').
  373.  
  374.   5. Yank the test expression into the minibuffer with `C-y' (`yank)'.
  375.  
  376.   6. Press <RET> to evaluate the expression.
  377.  
  378.    Emacs will print a graph that looks like this:
  379.  
  380.      10 -
  381.      
  382.      
  383.               *
  384.              **   *
  385.       5 -   ****  *
  386.             **** ***
  387.           * *********
  388.           ************
  389.       1 - *************
  390.      
  391.           |   |    |    |
  392.           1   5   10   15
  393.  
  394.    On the other hand, if you pass `print-graph' a `vertical-step' value
  395. of 2, by evaluating this expression:
  396.  
  397.      (print-graph '(3 2 5 6 7 5 3 4 6 4 3 2 1) 2)
  398.  
  399. The graph looks like this:
  400.  
  401.      20 -
  402.      
  403.      
  404.               *
  405.              **   *
  406.      10 -   ****  *
  407.             **** ***
  408.           * *********
  409.           ************
  410.       2 - *************
  411.      
  412.           |   |    |    |
  413.           1   5   10   15
  414.  
  415. (A question: is the `2' on the bottom of the vertical axis a bug or a
  416. feature?  If you think it is a bug, and should be a `1' instead, (or
  417. even a `0'), you can modify the sources.)
  418.  
  419. 
  420. File: emacs-lisp-intro.info,  Node: Graphing words in defuns,  Next: Final Printed Graph,  Prev: Test print-graph,  Up: Print Whole Graph
  421.  
  422. Graphing Numbers of Words and Symbols
  423. -------------------------------------
  424.  
  425.    Now for the graph for which all this code was written: a graph that
  426. shows how many function definitions contain fewer than 10 words and
  427. symbols, how many contain between 10 and 19 words and symbols, how many
  428. contain between 20 and 29 words and symbols, and so on.
  429.  
  430.    This is a multi-step process.  First make sure you have loaded all
  431. the requisit code.
  432.  
  433.    It is a good idea to reset the value of `top-of-ranges' in case you
  434. have sent it to some different value.  You can evaluate the following:
  435.  
  436.      (setq top-of-ranges
  437.       '(10  20  30  40  50
  438.         60  70  80  90 100
  439.        110 120 130 140 150
  440.        160 170 180 190 200
  441.        210 220 230 240 250
  442.        260 270 280 290 300)
  443.  
  444. Next create a list of the number of words and symbols in each range.
  445.  
  446. Evaluate the following:
  447.  
  448.      (setq list-for-graph
  449.             (defuns-per-range
  450.               (sort
  451.                (recursive-lengths-list-many-files
  452.                 (directory-files "/usr/local/emacs/lisp"
  453.                                  t ".+el$"))
  454.                '<)
  455.               top-of-ranges))
  456.  
  457. On my machine, this takes about an hour.  It looks though 303 Lisp
  458. files in my copy of Emacs version 19.23.  After all that computing, the
  459. `list-for-graph' has this value:
  460.  
  461.      (537 1027 955 785 594 483 349 292 224 199 166 120 116 99
  462.      90 80 67 48 52 45 41 33 28 26 25 20 12 28 11 13 220)
  463.  
  464. This means that my copy of Emacs has 537 function definitions with
  465. fewer than 10 words or symbols in them, 1,027 function definitions with
  466. 10 to 19 words or symbols in them, 955 function definitions with 20 to
  467. 29 words or symbols in them, and so on.
  468.  
  469.    Clearly, just by looking at this list we can see that most function
  470. definitions contain ten to thirty words and symbols.
  471.  
  472.    Now for printing.  We do *not* want to print a graph that is 1,030
  473. lines high ...  Instead, we should print a graph that is fewer than
  474. twenty-five lines high.  A graph that height can be displayed on almost
  475. any monitor, and easily printed on a sheet of paper.
  476.  
  477.    This means that each value in `list-for-graph' must be reduced to
  478. one-fiftieth it present value.
  479.  
  480.    Here is a short function to do just that, using two functions we have
  481. not yet seen, `mapcar' and `lambda'.
  482.  
  483.      (defun one-fiftieth (full-range)
  484.        "Return list, each number one-fiftieth of previous."
  485.       (mapcar '(lambda (arg) (/ arg 50)) full-range))
  486.  
  487. * Menu:
  488.  
  489. * lambda::                      How to write an anonymous function.
  490. * mapcar::                      Apply a function to elements of a list.
  491. * Another Bug::                 Yet another ... of a most insidious type.
  492.  
  493. 
  494. File: emacs-lisp-intro.info,  Node: lambda,  Next: mapcar,  Prev: Graphing words in defuns,  Up: Graphing words in defuns
  495.  
  496. A `lambda' Expression
  497. .....................
  498.  
  499.    `lambda' is the symbol for an anonymous function, a function without
  500. a name.  Every time you use an anonymous function, you need to include
  501. its whole body.
  502.  
  503. Thus,
  504.  
  505.      (lambda (arg) (/ arg 50))
  506.  
  507. is a function definition that says `return the value resulting from
  508. dividing whatever is passed to me as `arg' by 50'.
  509.  
  510.    Earlier, for example, we had a function `multiply-by-seven'; it
  511. multiplied its argument by 7.  This function is similar, except it
  512. divides its argument by 50; and, it has no name.  The anonymous
  513. equivalent of `multiply-by-seven' is:
  514.  
  515.      (lambda (number) (* 7 number))
  516.  
  517. (*Note The `defun' Special Form: defun.)
  518.  
  519. If we want to multiply 3 by 7, we can write:
  520.  
  521.      (multiply-by-seven 3)
  522.       \_______________/ ^
  523.               |         |
  524.            function  argument
  525.  
  526. This expression returns 21.
  527.  
  528. Similarly, we can write:
  529.  
  530.      ((lambda (number) (* 7 number)) 3)
  531.       \____________________________/ ^
  532.                     |                |
  533.            anonymous function     argument
  534.  
  535. If we want to divide 100 by 50, we can write:
  536.  
  537.      ((lambda (arg) (/ arg 50)) 100)
  538.       \______________________/  \_/
  539.                   |              |
  540.          anonymous function   argument
  541.  
  542. This expression returns 2.  The 100 is passed to the function, which
  543. divides that number by 50.
  544.  
  545.    *Note Lambda Expressions: (elisp)Lambda Expressions, for more about
  546. `lambda'.  Lisp and lambda expressions derive from the Lambda Calculus.
  547.  
  548. 
  549. File: emacs-lisp-intro.info,  Node: mapcar,  Next: Another Bug,  Prev: lambda,  Up: Graphing words in defuns
  550.  
  551. The `mapcar' Function
  552. .....................
  553.  
  554.    `mapcar' is a function that calls its first argument with each
  555. element of its second argument, in turn.  The second argument must be a
  556. sequence.
  557.  
  558. For example,
  559.  
  560.      (mapcar '1+ '(2 4 6))
  561.           => (3 5 7)
  562.  
  563. The function `1+' which adds one to its argument, is executed on *each*
  564. element of the list, and a new list is returned.
  565.  
  566.    Contrast this with `apply', which applies its first argument to all
  567. the remaining.  (*Note Readying a Graph: Readying a Graph, for a
  568. explanation of `apply'.)
  569.  
  570.    In the definition of `one-fiftieth', the first argument is the
  571. anonymous function:
  572.  
  573.      (lambda (arg) (/ arg 50))
  574.  
  575. and the second argument is `full-range', which will be bound to
  576. `list-for-graph'.
  577.  
  578.    The whole expression looks like this:
  579.  
  580.      (mapcar '(lambda (arg) (/ arg 50)) full-range))
  581.  
  582.    *Note Mapping Functions: (elisp)Mapping Functions, for more about
  583. `mapcar'.
  584.  
  585.    Using the `one-fiftieth' function, we can generate a list in which
  586. each element is one-fiftieth the size of the corresponding element in
  587. `list-for-graph'.
  588.  
  589.      (setq fiftieth-list-for-graph
  590.            (one-fiftieth list-for-graph))
  591.  
  592.    The resulting list looks like this:
  593.  
  594.      (10 20 19 15 11 9 6 5 4 3 3 2 2
  595.      1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 4)
  596.  
  597. This we are almost ready to print!  (We also notice the loss of
  598. information: many of the higher ranges are 0, meaning that fewer than
  599. 50 defuns had that many words or symbols--but not necessarily meaning
  600. that none had that many words or symbols.)
  601.  
  602. 
  603. File: emacs-lisp-intro.info,  Node: Another Bug,  Prev: mapcar,  Up: Graphing words in defuns
  604.  
  605. Another Bug ... Most Insidious
  606. ..............................
  607.  
  608.    I said `almost ready to print'!  Of course, there is a bug in the
  609. `print-graph' function ...  It has a `vertical-step' option, but not a
  610. `horizontal-step' option.  The `top-of-range' scale goes from 10 to 300
  611. by tens.  But the `print-graph' function will print only by ones.
  612.  
  613.    This is a classic example of what some consider the most insidious
  614. type of bug, the bug of omission.  This is not the kind of bug you can
  615. find by studying the code, for it is not in the code; it is an omitted
  616. feature.  Your best actions are to try your program early and often;
  617. and try to arrange, as much as you can, to write code that is easy to
  618. understand and easy to change.  Try to be aware, whenever you can, that
  619. whatever you have written, *will* be rewritten, if not soon,
  620. eventually.  A hard maxim to follow.
  621.  
  622.    It is the `print-X-axis-numbered-line' function that needs the work;
  623. and then the `print-X-axis' and the `print-graph' functions need to be
  624. adapted.  Not much needs to be done; there is one nicety: the numbers
  625. ought to line up under the tic marks.  This takes a little thought.
  626.  
  627.    Here is the corrected `print-X-axis-numbered-line':
  628.  
  629.      (defun print-X-axis-numbered-line
  630.        (number-of-X-tics X-axis-leading-spaces
  631.         &optional horizontal-step)
  632.        "Print line of X-axis numbers"
  633.        (let ((number X-axis-label-spacing)
  634.              (horizontal-step (or horizontal-step 1)))
  635.          (insert X-axis-leading-spaces)
  636.          ;; Delete extra leading spaces.
  637.          (delete-char
  638.           (- (1-
  639.               (length (int-to-string horizontal-step)))))
  640.          (insert (concat
  641.                   (make-string
  642.                    ;; Insert white space.
  643.                    (-  (* symbol-width
  644.                           X-axis-label-spacing)
  645.                        (1-
  646.                         (length
  647.                          (int-to-string horizontal-step)))
  648.                        2)
  649.                    ? )
  650.                   (int-to-string
  651.                    (* number horizontal-step))))
  652.          ;; Insert remaining numbers.
  653.          (setq number (+ number X-axis-label-spacing))
  654.          (while (> number-of-X-tics 1)
  655.            (insert (X-axis-element
  656.                     (* number horizontal-step)))
  657.            (setq number (+ number X-axis-label-spacing))
  658.            (setq number-of-X-tics (1- number-of-X-tics)))))
  659.  
  660.    If you are reading this in Info, you can see the new versions of
  661. `print-X-axis' `print-graph' and evaluate them.  If you are reading
  662. this in a printed book, you can see the changed lines here (the full
  663. text is too much to print).
  664.  
  665.      (defun print-X-axis (numbers-list horizontal-step)
  666.        "Print X axis labels to length of NUMBERS-LIST.
  667.      Optionally, HORIZONTAL-STEP, a positive integer,
  668.      specifies how much an X  axis label increments for
  669.      each column."
  670.      ;; Value of symbol-width and full-Y-label-width
  671.      ;; are passed by `print-graph'.
  672.        (let* ((leading-spaces
  673.                (make-string full-Y-label-width ? ))
  674.             ;; symbol-width is provided by graph-body-print
  675.             (tic-width (* symbol-width X-axis-label-spacing))
  676.             (X-length (length numbers-list))
  677.             (X-tic
  678.              (concat
  679.               (make-string
  680.                ;; Make a string of blanks.
  681.                (-  (* symbol-width X-axis-label-spacing)
  682.                    (length X-axis-tic-symbol))
  683.                ? )
  684.               ;; Concatenate blanks with tic symbol.
  685.               X-axis-tic-symbol))
  686.             (tic-number
  687.              (if (zerop (% X-length tic-width))
  688.                  (/ X-length tic-width)
  689.                (1+ (/ X-length tic-width)))))
  690.      
  691.          (print-X-axis-tic-line
  692.           tic-number leading-spaces X-tic)
  693.          (insert "\n")
  694.          (print-X-axis-numbered-line
  695.           tic-number leading-spaces horizontal-step)))
  696.  
  697.      (defun print-graph
  698.        (numbers-list &optional vertical-step horizontal-step)
  699.        "Print labelled bar graph of the NUMBERS-LIST.
  700.      The numbers-list consists of the Y-axis values.
  701.      
  702.      Optionally, VERTICAL-STEP, a positive integer,
  703.      specifies how much a Y axis label increments for
  704.      each line.  For example, a step of 5 means that
  705.      each row is five units.
  706.      
  707.      Optionally, HORIZONTAL-STEP, a positive integer,
  708.      specifies how much an X  axis label increments for
  709.      each column."
  710.        (let* ((symbol-width (length graph-blank))
  711.               ;; `height' is both the largest number
  712.               ;; and the number with the most digits.
  713.               (height (apply 'max numbers-list))
  714.               (height-of-top-line
  715.                (if (zerop (% height Y-axis-label-spacing))
  716.                    height
  717.                  ;; else
  718.                  (* (1+ (/ height Y-axis-label-spacing))
  719.                     Y-axis-label-spacing)))
  720.               (vertical-step (or vertical-step 1))
  721.               (full-Y-label-width
  722.                (length
  723.                 (concat
  724.                  (int-to-string
  725.                   (* height-of-top-line vertical-step))
  726.                  Y-axis-tic))))
  727.          (print-Y-axis
  728.           height-of-top-line full-Y-label-width vertical-step)
  729.          (graph-body-print
  730.              numbers-list height-of-top-line symbol-width)
  731.          (print-X-axis numbers-list horizontal-step)))
  732.  
  733. 
  734. File: emacs-lisp-intro.info,  Node: Final Printed Graph,  Prev: Graphing words in defuns,  Up: Print Whole Graph
  735.  
  736. The Printed Graph
  737. -----------------
  738.  
  739.    When made and installed, you can call the `print-graph' command like
  740. this:
  741.  
  742.      (print-graph fiftieth-list-for-graph 50 10)
  743.  
  744.    Here is the graph:
  745.  
  746.      1000 -  *
  747.              **
  748.              **
  749.              **
  750.              **
  751.       750 -  ***
  752.              ***
  753.              ***
  754.              ***
  755.              ****
  756.       500 - *****
  757.             ******
  758.             ******
  759.             ******
  760.             *******
  761.       250 - ********
  762.             *********                     *
  763.             ***********                   *
  764.             *************                 *
  765.        50 - ***************** *           *
  766.             |   |    |    |    |    |    |    |
  767.            10  50  100  150  200  250  300  350
  768.  
  769.    The largest group of functions contain 10 - 19 words and symbols
  770. each.
  771.  
  772. 
  773. File: emacs-lisp-intro.info,  Node: Index,  Next: About the Author,  Prev: Full Graph,  Up: Top
  774.  
  775. Index
  776. *****
  777.  
  778.    MENU ENTRY: NODE NAME.
  779.  
  780. * Menu:
  781.  
  782. * % (remainder function):                Compute a Remainder.
  783. * (debug) in code:                       debug-on-quit.
  784. * * (multiplication):                    defun.
  785. * * for read-only buffer:                read-only buffer.
  786. * *Backtrace* buffer:                    debug.
  787. * *scratch* buffer:                      print-elements-of-list.
  788. * .emacs file:                           Emacs Initialization.
  789. * .emacs file, beginning of:             Beginning a .emacs File.
  790. * / (division):                          large-case.
  791. * <= (less than or equal):               Inc Example parts.
  792. * > (greater than):                      if.
  793. * add-hook:                              Text and Auto-fill.
  794. * and:                                   fwd-para let.
  795. * Anonymous function:                    lambda.
  796. * append-to-buffer:                      append-to-buffer.
  797. * apply:                                 Columns of a graph.
  798. * apropos:                               Columns of a graph.
  799. * Argument as local variable:            Dec Example altogether.
  800. * argument defined:                      Arguments.
  801. * argument list defined:                 defun.
  802. * Argument, wrong type of:               Wrong Type of Argument.
  803. * Arguments:                             Arguments.
  804. * Arguments' data types:                 Data types.
  805. * Arguments, variable number of:         Variable Number of Arguments.
  806. * Asterisk for read-only buffer:         read-only buffer.
  807. * Auto Fill mode turned on:              Text and Auto-fill.
  808. * autoload:                              Autoload.
  809. * Automatic mode selection:              Text and Auto-fill.
  810. * Axis, print horizontal:                print-X-axis.
  811. * Axis, print vertical:                  print-Y-axis.
  812. * Backtrace buffer for debugging:        debug.
  813. * beginning-of-buffer:                   beginning-of-buffer.
  814. * bind defined:                          set & setq.
  815. * body defined:                          defun.
  816. * Body of graph:                         Readying a Graph.
  817. * Buffer size:                           Buffer Size & Locations.
  818. * Buffer, history of word:               Buffer Names.
  819. * buffer-file-name:                      Buffer Names.
  820. * buffer-menu, bound to key:             Keybindings.
  821. * buffer-name:                           Buffer Names.
  822. * Bug, most insidious type:              Another Bug.
  823. * Byte compiling:                        Byte Compiling.
  824. * C language primitives:                 Primitive Functions.
  825. * C, a digression into:                  delete-region.
  826. * call defined:                          Switching Buffers.
  827. * cancel-debug-on-entry:                 debug-on-entry.
  828. * car, introduced:                       car cdr & cons.
  829. * cdr, introduced:                       car cdr & cons.
  830. * Changing a function definition:        Change a defun.
  831. * Clipping text:                         Cutting & Storing Text.
  832. * Code installation:                     Permanent Installation.
  833. * command defined:                       How to Evaluate.
  834. * Comments in Lisp code:                 Change a defun.
  835. * Common Lisp:                           Lisp History.
  836. * compare-windows:                       Keybindings.
  837. * concat:                                Data types.
  838. * cond:                                  Recursion with cond.
  839. * Conditional 'twixt Emacs 18 and 19:    Simple Extension.
  840. * Conditional with if:                   if.
  841. * cons, introduced:                      cons.
  842. * copy-region-as-kill:                   copy-region-as-kill.
  843. * copy-to-buffer:                        copy-to-buffer.
  844. * Count words recursively:               recursive-count-words.
  845. * count-words-in-defun:                  count-words-in-defun.
  846. * count-words-region:                    count-words-region.
  847. * Counting:                              Counting.
  848. * Counting words in a defun <1>:         count-words-in-defun.
  849. * Counting words in a defun:             Words in a defun.
  850. * current-buffer:                        Getting Buffers.
  851. * Customizing your .emacs file:          Emacs Initialization.
  852. * Cutting and storing text:              Cutting & Storing Text.
  853. * Data types:                            Data types.
  854. * debug:                                 debug.
  855. * debug-on-entry:                        debug-on-entry.
  856. * debug-on-error:                        debug.
  857. * debug-on-quit:                         debug-on-quit.
  858. * debugging:                             Debugging.
  859. * default-mode-line-format:              Mode Line.
  860. * default.el init file:                  Site-wide Init.
  861. * Definition installation:               Install.
  862. * Definition writing:                    Writing Defuns.
  863. * Definition, how to change:             Change a defun.
  864. * defun:                                 defun.
  865. * defvar:                                defvar.
  866. * delete-region:                         delete-region.
  867. * Deleting text:                         Cutting & Storing Text.
  868. * describe-function:                     simplified-beginning-of-buffer.
  869. * describe-function, introduced:         Finding More.
  870. * Digression into C:                     delete-region.
  871. * directory-files:                       Files List.
  872. * Division:                              large-case.
  873. * Duplicated words function:             the-the.
  874. * edebug:                                edebug.
  875. * edit-options:                          edit-options.
  876. * edit-options, introduced:              defvar.
  877. * Else:                                  else.
  878. * Emacs version, choosing:               Simple Extension.
  879. * empty list defined:                    Lisp Atoms.
  880. * eobp:                                  fwd-para between paragraphs.
  881. * eq:                                    Review.
  882. * eq (example of use):                   copy-region-as-kill body.
  883. * equal:                                 Review.
  884. * Erasing text:                          Cutting & Storing Text.
  885. * error:                                 rotate-yk-ptr body.
  886. * Error for symbol without value:        Void Variable.
  887. * Error message generation:              Making Errors.
  888. * etags:                                 etags.
  889. * evaluate defined:                      Run a Program.
  890. * Evaluating inner lists:                Evaluating Inner Lists.
  891. * Evaluation:                            Evaluation.
  892. * Evaluation practice:                   Practicing Evaluation.
  893. * expression defined:                    Lisp Atoms.
  894. * Falsehood and truth in Lisp:           Truth & Falsehood.
  895. * Find a File:                           Find a File.
  896. * Find function documentation:           Finding More.
  897. * Find source of function:               Finding More.
  898. * find-tags:                             Finding More.
  899. * Flowers in a field:                    Lisp Lists.
  900. * Focusing attention (narrowing):        Narrowing & Widening.
  901. * form defined:                          Lisp Atoms.
  902. * Formatting convention:                 append save-excursion.
  903. * Formatting help:                       Typing Lists.
  904. * forward-paragraph:                     forward-paragraph.
  905. * forward-sentence:                      forward-sentence.
  906. * function defined:                      Making Errors.
  907. * function definition defined:           defun.
  908. * Function definition installation:      Install.
  909. * Function definition writing:           Writing Defuns.
  910. * Function definition, how to change:    Change a defun.
  911. * Functions, primitive:                  Primitive Functions.
  912. * Generate an error message:             Making Errors.
  913. * Getting a buffer:                      Getting Buffers.
  914. * Global set key:                        Keybindings.
  915. * global-set-key:                        Keybindings.
  916. * global-unset-key:                      Keybindings.
  917. * Graph prototype:                       Readying a Graph.
  918. * Graph, printing all:                   Print Whole Graph.
  919. * graph-body-print:                      graph-body-print.
  920. * graph-body-print Final version.:       Print Whole Graph.
  921. * Handling the kill ring:                Kill Ring.
  922. * Help typing lists:                     Typing Lists.
  923. * Horizontal axis printing:              print-X-axis.
  924. * if:                                    if.
  925. * if-part defined:                       if.
  926. * indent-tabs-mode:                      Indent Tabs Mode.
  927. * Indentation for formatting:            append save-excursion.
  928. * Initialization file:                   Emacs Initialization.
  929. * Initializing a variable:               defvar.
  930. * Inner list evaluation:                 Evaluating Inner Lists.
  931. * insert-buffer:                         insert-buffer.
  932. * insert-buffer-substring:               append-to-buffer.
  933. * Insidious type of bug:                 Another Bug.
  934. * Install a Function Definition:         Install.
  935. * Install code permanently:              Permanent Installation.
  936. * int-to-string:                         Y Axis Element.
  937. * interactive:                           Interactive.
  938. * interactive function defined:          How to Evaluate.
  939. * Interactive functions:                 Interactive.
  940. * Interactive options:                   Interactive Options.
  941. * interactive, example use of:           insert interactive expression.
  942. * Interpreter, Lisp, explained:          Run a Program.
  943. * Interpreter, what it does:             Lisp Interpreter.
  944. * Key setting globally:                  Keybindings.
  945. * Key unbinding:                         Keybindings.
  946. * Keymaps:                               Keymaps.
  947. * Keyword:                               Optional Arguments.
  948. * Kill ring handling:                    Kill Ring.
  949. * Kill ring overview:                    Kill Ring Overview.
  950. * kill-append:                           kill-append function.
  951. * kill-region:                           kill-region.
  952. * Killing text:                          Cutting & Storing Text.
  953. * lambda:                                lambda.
  954. * length:                                length.
  955. * lengths-list-file:                     lengths-list-file.
  956. * lengths-list-many-files:               Several files.
  957. * let:                                   let.
  958. * let expression sample:                 Sample let Expression.
  959. * let expression, parts of:              Parts of let Expression.
  960. * let variables uninitialized:           Uninitialized let Variables.
  961. * Library, as term for `file':           Finding More.
  962. * line-to-top-of-window:                 Simple Extension.
  963. * Lisp Atoms:                            Lisp Atoms.
  964. * Lisp history:                          Lisp History.
  965. * Lisp interpreter, explained:           Run a Program.
  966. * Lisp interpreter, what it does:        Lisp Interpreter.
  967. * Lisp Lists:                            Lisp Lists.
  968. * list-buffers, rebound:                 Keybindings.
  969. * list-options:                          edit-options.
  970. * Lists in a computer:                   List Implementation.
  971. * load-library:                          Loading Files.
  972. * load-path:                             Loading Files.
  973. * Loading files:                         Loading Files.
  974. * local variable defined:                let.
  975. * Local variables list, per-buffer,:     Text and Auto-fill.
  976. * Location of point:                     Buffer Size & Locations.
  977. * looking-at:                            fwd-para between paragraphs.
  978. * Loops:                                 while.
  979. * Loops and recursion:                   Loops & Recursion.
  980. * Maclisp:                               Lisp History.
  981. * Mail aliases:                          Mail Aliases.
  982. * make-string:                           Y Axis Element.
  983. * mapcar:                                mapcar.
  984. * mark:                                  save-excursion.
  985. * mark-whole-buffer:                     mark-whole-buffer.
  986. * match-beginning:                       fwd-para no fill prefix.
  987. * max:                                   Columns of a graph.
  988. * message:                               message.
  989. * min:                                   Columns of a graph.
  990. * Mode line format:                      Mode Line.
  991. * Mode selection, automatic:             Text and Auto-fill.
  992. * Motion by sentence and paragraph:      Regexp Search.
  993. * Narrowing:                             Narrowing & Widening.
  994. * narrowing defined:                     Buffer Size & Locations.
  995. * nil:                                   Truth & Falsehood.
  996. * nil, history of word:                  Buffer Names.
  997. * nreverse:                              Files List.
  998. * nthcdr <1>:                            copy-region-as-kill.
  999. * nthcdr:                                nthcdr.
  1000. * occur:                                 Keybindings.
  1001. * optional:                              Optional Arguments.
  1002. * Optional arguments:                    Optional Arguments.
  1003. * Options for interactive:               Interactive Options.
  1004. * Options introduced:                    defvar.
  1005. * Options, easily settable:              edit-options.
  1006. * or:                                    insert or.
  1007. * other-buffer:                          Getting Buffers.
  1008. * Paragraphs, movement by:               Regexp Search.
  1009. * Parts of let expression:               Parts of let Expression.
  1010. * Passing information to functions:      Arguments.
  1011. * Pasting text:                          Yanking.
  1012. * Patterns, searching for:               Regexp Search.
  1013. * Per-buffer, local variables list:      Text and Auto-fill.
  1014. * Permanent code installation:           Permanent Installation.
  1015. * point:                                 save-excursion.
  1016. * point defined:                         Buffer Size & Locations.
  1017. * Point location:                        Buffer Size & Locations.
  1018. * Point, mark, buffer preservation:      save-excursion.
  1019. * Practicing evaluation:                 Practicing Evaluation.
  1020. * Preserving point, mark, and buffer:    save-excursion.
  1021. * Primitive functions:                   Primitive Functions.
  1022. * Primitives written in C:               Primitive Functions.
  1023. * Print horizontal axis:                 print-X-axis.
  1024. * Print vertical axis:                   print-Y-axis.
  1025. * print-elements-of-list:                print-elements-of-list.
  1026. * print-elements-recursively:            Recursion with list.
  1027. * print-graph Final version.:            Print Whole Graph.
  1028. * print-graph varlist:                   print-graph Varlist.
  1029. * print-X-axis:                          X Axis Tic Marks.
  1030. * print-X-axis-numbered-line:            X Axis Tic Marks.
  1031. * print-X-axis-tic-line:                 X Axis Tic Marks.
  1032. * print-Y-axis:                          print-Y-axis Final.
  1033. * Printing the whole graph:              Print Whole Graph.
  1034. * prog1:                                 fwd-para between paragraphs.
  1035. * progn:                                 progn.
  1036. * Program, running one:                  Run a Program.
  1037. * Prototype graph:                       Readying a Graph.
  1038. * re-search-forward:                     re-search-forward.
  1039. * Read-only buffer:                      read-only buffer.
  1040. * Readying a graph:                      Readying a Graph.
  1041. * Rebinding keys:                        Keymaps.
  1042. * Recursion:                             Recursion.
  1043. * Recursion and loops:                   Loops & Recursion.
  1044. * recursive-count-words:                 recursive-count-words.
  1045. * recursive-graph-body-print:            recursive-graph-body-print.
  1046. * recursive-lengths-list-many-files:     Several files recursively.
  1047. * Recursively counting words:            recursive-count-words.
  1048. * regexp-quote:                          fwd-para let.
  1049. * Region, what it is:                    save-excursion.
  1050. * Regular expression searches:           Regexp Search.
  1051. * Regular expressions for word counting: Counting Words.
  1052. * Remainder function, %:                 Compute a Remainder.
  1053. * Repetition (loops):                    Loops & Recursion.
  1054. * Repetition for word counting:          Counting Words.
  1055. * Retrieving text:                       Yanking.
  1056. * reverse:                               Files List.
  1057. * Ring, making a list like a:            Kill Ring.
  1058. * rotate-yank-pointer <1>:               rotate-yank-pointer.
  1059. * rotate-yank-pointer:                   Yanking.
  1060. * Run a program:                         Run a Program.
  1061. * Sample let expression:                 Sample let Expression.
  1062. * save-excursion:                        save-excursion.
  1063. * save-restriction:                      save-restriction.
  1064. * search-forward:                        search-forward.
  1065. * Searches, illustrating:                Regexp Search.
  1066. * sentence-end:                          sentence-end.
  1067. * Sentences, movement by:                Regexp Search.
  1068. * set:                                   Using set.
  1069. * set-buffer:                            Switching Buffers.
  1070. * setcar:                                setcar.
  1071. * setcdr:                                setcdr.
  1072. * setq:                                  Using setq.
  1073. * Setting a key globally:                Keybindings.
  1074. * Setting value of variable:             set & setq.
  1075. * side effect defined:                   Evaluation.
  1076. * Simple extension in .emacs file:       Simple Extension.
  1077. * simplified-beginning-of-buffer:        simplified-beginning-of-buffer.
  1078. * site-init.el init file:                Site-wide Init.
  1079. * site-load.el init file:                Site-wide Init.
  1080. * Size of buffer:                        Buffer Size & Locations.
  1081. * sort:                                  Sorting.
  1082. * Source level debugger:                 edebug.
  1083. * Special form:                          Lisp Interpreter.
  1084. * Special form of defun:                 defun.
  1085. * Storing and cutting text:              Cutting & Storing Text.
  1086. * string defined:                        Lisp Atoms.
  1087. * switch-to-buffer:                      Switching Buffers.
  1088. * Switching to a buffer:                 Switching Buffers.
  1089. * Symbol names:                          Names & Definitions.
  1090. * Symbol without value error:            Void Variable.
  1091. * Symbolic expressions, introduced:      Lisp Atoms.
  1092. * Syntax categories and tables:          Syntax.
  1093. * Tabs, preventing:                      Indent Tabs Mode.
  1094. * TAGS file, create own:                 etags.
  1095. * TAGS table, specifying:                Finding More.
  1096. * Text between double quotation marks:   Lisp Atoms.
  1097. * Text Mode turned on:                   Text and Auto-fill.
  1098. * Text retrieval:                        Yanking.
  1099. * the-the:                               the-the.
  1100. * then-part defined:                     if.
  1101. * top-of-ranges:                         Files List.
  1102. * triangle-bugged:                       debug.
  1103. * triangle-recursively:                  Recursive triangle function.
  1104. * Truth and falsehood in Lisp:           Truth & Falsehood.
  1105. * Types of data:                         Data types.
  1106. * Unbinding key:                         Keybindings.
  1107. * Uninitialized let variables:           Uninitialized let Variables.
  1108. * Variable initialization:               defvar.
  1109. * Variable number of arguments:          Variable Number of Arguments.
  1110. * Variable, setting value:               set & setq.
  1111. * Variables:                             Variables.
  1112. * varlist defined:                       Parts of let Expression.
  1113. * Version of Emacs, choosing:            Simple Extension.
  1114. * Vertical axis printing:                print-Y-axis.
  1115. * what-line:                             what-line.
  1116. * while:                                 while.
  1117. * Whitespace in lists:                   Whitespace in Lists.
  1118. * Whole graph printing:                  Print Whole Graph.
  1119. * Widening:                              Narrowing & Widening.
  1120. * Widening, example of:                  what-line.
  1121. * Word counting in a defun:              Words in a defun.
  1122. * Words and symbols in defun:            Words and Symbols.
  1123. * Words, counted recursively:            recursive-count-words.
  1124. * Words, duplicated:                     the-the.
  1125. * Writing a function definition:         Writing Defuns.
  1126. * Wrong type of argument:                Wrong Type of Argument.
  1127. * X axis printing:                       print-X-axis.
  1128. * X-axis-element:                        X Axis Tic Marks.
  1129. * Y axis printing:                       print-Y-axis.
  1130. * Y-axis-column:                         Y-axis-column.
  1131. * Y-axis-column Final version.:          Print Whole Graph.
  1132. * Y-axis-label-spacing:                  Compute a Remainder.
  1133. * Y-axis-tic:                            Y Axis Element.
  1134. * yank <1>:                              yank.
  1135. * yank:                                  Yanking.
  1136. * yank-pop:                              yank-pop.
  1137. * zap-to-char:                           zap-to-char.
  1138. * zerop:                                 rotate-yk-ptr body.
  1139.  
  1140. 
  1141. File: emacs-lisp-intro.info,  Node: About the Author,  Prev: Index,  Up: Top
  1142.  
  1143. About the Author
  1144. ****************
  1145.  
  1146.      Robert J. Chassell has worked with GNU Emacs since 1985.  He writes
  1147.      and edits, teaches Emacs and Emacs Lisp, and is a director and the
  1148.      Secretary/Treasurer of the Free Software Foundation, Inc.  He has
  1149.      an abiding interest in social and economic history and flies his
  1150.      own airplane.
  1151.  
  1152.     
  1153.  
  1154.  
  1155.